import { IContextDescriptionItem } from '@/apis/chat/interfaces'
import { Flow } from '@leafer-in/flow'
import anime from 'animejs'
import { Box, IUI, Rect } from 'leafer-ui'
import { ref } from 'vue'
import { uiItems } from './uiItems'

export const started = ref(false)

export const isAnimation = ref(false)

export const infoText = ref('未开始')

export const config = {
    duration: 200,
}

// 待排序的元素
let globalArr: number[] = []
// 要做动画的rect
let globalRects: Rect[] = []
// 生成器
let generator: AsyncGenerator<undefined, void, unknown> | null = null

// 插入排序
export const insertionSort = (arr: number[]) => {
    for (let i = 1; i < arr.length; i++) {
        const key = arr[i]
        let j = i - 1
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j]
            j--
        }
        arr[j + 1] = key
    }
}

export const setInfo = (str: string) => {
    // console.log(str)
    infoText.value = str
}

// 交换两个矩形的位置
const exchangeRect = async (i: number, j: number) => {
    const iRect = globalRects[i]
    const jRect = globalRects[j]
    const ix = iRect.x
    const jx = jRect.x
    const tempRect = globalRects[j]
    globalRects[j] = globalRects[i]
    globalRects[i] = tempRect
    await Promise.all([
        anime({
            targets: iRect,
            x: jx,
            duration: config.duration,
            easing: 'linear',
        }).finished,
        anime({
            targets: jRect,
            x: ix,
            duration: config.duration,
            easing: 'linear',
        }).finished,
    ])
}

// 更改矩形的颜色
export const changeRectColor = async (rect: IUI, color: string) => {
    return anime({
        targets: rect,
        fill: color,
        duration: config.duration,
        easing: 'linear',
        update: () => {
            rect.forceUpdate()
        },
    }).finished
}

// 生成器函数
export async function* insertSortGenerator(arr: number[]) {
    started.value = true
    setInfo(`开始排序`)
    yield
    for (let i = 1; i < arr.length; i++) {
        const key = arr[i]
        const keyRect = globalRects[i]
        let j = i - 1
        setInfo(`检查第 ${i} 项是否小于前一项`)
        await changeRectColor(keyRect, '#4279e4')
        yield
        await changeRectColor(globalRects[j], '#fbaf46')
        yield
        while (j >= 0 && arr[j] > key) {
            setInfo(
                `第 ${i} 小于前一项，所以把前一项的值赋值给后一项，并往前检查`
            )
            await exchangeRect(j + 1, j)
            await changeRectColor(globalRects[j + 1], '#ededed')
            await changeRectColor(globalRects[j - 1], '#fbaf46')
            arr[j + 1] = arr[j]
            j--
            yield
        }
        arr[j + 1] = key
        await Promise.all([changeRectColor(keyRect, '#ededed'), changeRectColor(globalRects[j], '#ededed')])
    }
}

// 初始化
export const init = (arr: number[]) => {
    started.value = false
    globalArr = arr
    // 画布的高度为500，数组中的最大值为4，所以每个元素对应的高度为500/4=125
    const max = Math.max(...arr)
    const unitHeight = 500 / max

    const rects = arr.map((num, i) => {
        const width = 30
        const gap = 10
        const height = num * unitHeight
        return new Flow({
            x: i * (width + gap),
            y: 500 - height,
            width,
            height,
            fill: '#ededed',
            flowAlign: 'bottom',
            children: [
                {
                    tag: 'Text',
                    text: num,
                    width,
                    textAlign: 'center',
                    verticalAlign: 'bottom',
                },
            ],
        })
    })

    globalRects = rects
    const container = uiItems.container as Box
    container.clear()
    container.add(rects)
    setTimeout(() => {
        container.app.tree?.zoom('fit')
    }, 1000)
}

// 开始
export const start = () => {
    generator = insertSortGenerator(globalArr)
    generator.next()
}

// 下一步
export const next = async () => {
    if (!generator || isAnimation.value) return
    isAnimation.value = true
    const res = await generator.next()
    isAnimation.value = false
    if (res.done) {
        setInfo('结束' + globalArr)
        started.value = false
        return
    }
}

// 运行到结束
export const runToEnd = async () => {
    if (!generator || isAnimation.value) return
    isAnimation.value = true
    const res = await generator.next()
    isAnimation.value = false
    if (res.done) {
        setInfo('结束' + globalArr)
        started.value = false
        return
    }
    await runToEnd()
}

export const getContextDescription: () => IContextDescriptionItem[] = () => {
    return [
        {
            key: 'caseTitle',
            value: '插入排序',
        },
        {
            key: 'caseDescription',
            value: '此案例演示了插入排序算法的运行过程',
        },
    ]
}
